cssstyle: Split into GtkCssStyle and GtkCssAnimatedStyle
authorBenjamin Otte <otte@redhat.com>
Thu, 23 Oct 2014 02:10:03 +0000 (04:10 +0200)
committerBenjamin Otte <otte@redhat.com>
Wed, 7 Jan 2015 13:26:46 +0000 (14:26 +0100)
GtkCssStyle is the base class to be used for all types of styles that do
exist.

GtkCssAnimatedStyle is the only implementation so far, that is exactly a
copy/paste of the old GtkCssStyle code.

12 files changed:
gtk/Makefile.am
gtk/gtkcssanimatedstyle.c [new file with mode: 0644]
gtk/gtkcssanimatedstyleprivate.h [new file with mode: 0644]
gtk/gtkcssanimation.c
gtk/gtkcsslookup.c
gtk/gtkcsslookupprivate.h
gtk/gtkcssstyle.c
gtk/gtkcssstyleprivate.h
gtk/gtkcsstransition.c
gtk/gtkstyleanimation.c
gtk/gtkstyleanimationprivate.h
gtk/gtkstylecontext.c

index d2ffbd885c5857222a3f6d3d4167445ef3950a79..0573e3e3787b765da0d865798b4f6cd5001a5b53 100644 (file)
@@ -368,6 +368,7 @@ gtk_private_h_sources =             \
        gtkcomboboxprivate.h    \
        gtkcontainerprivate.h   \
        gtkcssanimationprivate.h        \
+       gtkcssanimatedstyleprivate.h    \
        gtkcssarrayvalueprivate.h       \
        gtkcssbgsizevalueprivate.h      \
        gtkcssbordervalueprivate.h      \
@@ -592,6 +593,7 @@ gtk_base_c_sources =                \
        gtkcomboboxtext.c       \
        gtkcontainer.c          \
        gtkcssanimation.c       \
+       gtkcssanimatedstyle.c   \
        gtkcssarrayvalue.c      \
        gtkcssbgsizevalue.c     \
        gtkcssbordervalue.c     \
diff --git a/gtk/gtkcssanimatedstyle.c b/gtk/gtkcssanimatedstyle.c
new file mode 100644 (file)
index 0000000..4ced8d1
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtkcssanimatedstyleprivate.h"
+
+#include "gtkcssanimationprivate.h"
+#include "gtkcssarrayvalueprivate.h"
+#include "gtkcssenumvalueprivate.h"
+#include "gtkcssinheritvalueprivate.h"
+#include "gtkcssinitialvalueprivate.h"
+#include "gtkcssnumbervalueprivate.h"
+#include "gtkcsssectionprivate.h"
+#include "gtkcssshorthandpropertyprivate.h"
+#include "gtkcssstringvalueprivate.h"
+#include "gtkcssstylepropertyprivate.h"
+#include "gtkcsstransitionprivate.h"
+#include "gtkprivate.h"
+#include "gtkstyleanimationprivate.h"
+#include "gtkstylepropertyprivate.h"
+#include "gtkstyleproviderprivate.h"
+
+G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE)
+
+static GtkCssValue *
+gtk_css_animated_style_get_value (GtkCssStyle *style,
+                                  guint        id)
+{
+  GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+
+  if (animated->animated_values &&
+      id < animated->animated_values->len &&
+      g_ptr_array_index (animated->animated_values, id))
+    return g_ptr_array_index (animated->animated_values, id);
+
+  return gtk_css_animated_style_get_intrinsic_value (animated, id);
+}
+
+static GtkCssSection *
+gtk_css_animated_style_get_section (GtkCssStyle *style,
+                                    guint        id)
+{
+  GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+
+  if (animated->sections == NULL ||
+      id >= animated->sections->len)
+    return NULL;
+
+  return g_ptr_array_index (animated->sections, id);
+}
+
+static GtkBitmask *
+gtk_css_animated_style_compute_dependencies (GtkCssStyle      *style,
+                                             const GtkBitmask *parent_changes)
+{
+  GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
+  GtkBitmask *changes;
+
+  changes = _gtk_bitmask_copy (parent_changes);
+  changes = _gtk_bitmask_intersect (changes, animated->depends_on_parent);
+  if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
+    changes = _gtk_bitmask_union (changes, animated->depends_on_color);
+  if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
+    changes = _gtk_bitmask_union (changes, animated->depends_on_font_size);
+
+  return changes;
+}
+
+static void
+gtk_css_animated_style_dispose (GObject *object)
+{
+  GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
+
+  if (style->values)
+    {
+      g_ptr_array_unref (style->values);
+      style->values = NULL;
+    }
+  if (style->sections)
+    {
+      g_ptr_array_unref (style->sections);
+      style->sections = NULL;
+    }
+  if (style->animated_values)
+    {
+      g_ptr_array_unref (style->animated_values);
+      style->animated_values = NULL;
+    }
+
+  g_slist_free_full (style->animations, g_object_unref);
+  style->animations = NULL;
+
+  G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->dispose (object);
+}
+
+static void
+gtk_css_animated_style_finalize (GObject *object)
+{
+  GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
+
+  _gtk_bitmask_free (style->depends_on_parent);
+  _gtk_bitmask_free (style->equals_parent);
+  _gtk_bitmask_free (style->depends_on_color);
+  _gtk_bitmask_free (style->depends_on_font_size);
+
+  G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->finalize (object);
+}
+
+static void
+gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkCssStyleClass *style_class = GTK_CSS_STYLE_CLASS (klass);
+
+  object_class->dispose = gtk_css_animated_style_dispose;
+  object_class->finalize = gtk_css_animated_style_finalize;
+
+  style_class->get_value = gtk_css_animated_style_get_value;
+  style_class->get_section = gtk_css_animated_style_get_section;
+  style_class->compute_dependencies = gtk_css_animated_style_compute_dependencies;
+}
+
+static void
+gtk_css_animated_style_init (GtkCssAnimatedStyle *style)
+{
+  style->depends_on_parent = _gtk_bitmask_new ();
+  style->equals_parent = _gtk_bitmask_new ();
+  style->depends_on_color = _gtk_bitmask_new ();
+  style->depends_on_font_size = _gtk_bitmask_new ();
+}
+
+GtkCssStyle *
+gtk_css_animated_style_new (void)
+{
+  return g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
+}
+
+static void
+maybe_unref_section (gpointer section)
+{
+  if (section)
+    gtk_css_section_unref (section);
+}
+
+void
+gtk_css_animated_style_compute_value (GtkCssAnimatedStyle     *style,
+                                      GtkStyleProviderPrivate *provider,
+                                      int                      scale,
+                                      GtkCssStyle             *parent_style,
+                                      guint                    id,
+                                      GtkCssValue             *specified,
+                                      GtkCssSection           *section)
+{
+  GtkCssDependencies dependencies;
+  GtkCssValue *value;
+
+  gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+  gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
+  gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
+
+  /* http://www.w3.org/TR/css3-cascade/#cascade
+   * Then, for every element, the value for each property can be found
+   * by following this pseudo-algorithm:
+   * 1) Identify all declarations that apply to the element
+   */
+  if (specified == NULL)
+    {
+      GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (id);
+
+      if (_gtk_css_style_property_is_inherit (prop))
+        specified = _gtk_css_inherit_value_new ();
+      else
+        specified = _gtk_css_initial_value_new ();
+    }
+  else
+    _gtk_css_value_ref (specified);
+
+  value = _gtk_css_value_compute (specified, id, provider, scale, GTK_CSS_STYLE (style), parent_style, &dependencies);
+
+  if (style->values == NULL)
+    style->values = g_ptr_array_new_full (_gtk_css_style_property_get_n_properties (),
+                                          (GDestroyNotify)_gtk_css_value_unref);
+  if (id >= style->values->len)
+   g_ptr_array_set_size (style->values, id + 1);
+
+  if (g_ptr_array_index (style->values, id))
+    _gtk_css_value_unref (g_ptr_array_index (style->values, id));
+  g_ptr_array_index (style->values, id) = _gtk_css_value_ref (value);
+
+  if (dependencies & (GTK_CSS_DEPENDS_ON_PARENT | GTK_CSS_EQUALS_PARENT))
+    style->depends_on_parent = _gtk_bitmask_set (style->depends_on_parent, id, TRUE);
+  if (dependencies & (GTK_CSS_EQUALS_PARENT))
+    style->equals_parent = _gtk_bitmask_set (style->equals_parent, id, TRUE);
+  if (dependencies & (GTK_CSS_DEPENDS_ON_COLOR))
+    style->depends_on_color = _gtk_bitmask_set (style->depends_on_color, id, TRUE);
+  if (dependencies & (GTK_CSS_DEPENDS_ON_FONT_SIZE))
+    style->depends_on_font_size = _gtk_bitmask_set (style->depends_on_font_size, id, TRUE);
+
+  if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
+    {
+      gtk_css_section_unref (g_ptr_array_index (style->sections, id));
+      g_ptr_array_index (style->sections, id) = NULL;
+    }
+
+  if (section)
+    {
+      if (style->sections == NULL)
+        style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
+      if (style->sections->len <= id)
+        g_ptr_array_set_size (style->sections, id + 1);
+
+      g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
+    }
+
+  _gtk_css_value_unref (value);
+  _gtk_css_value_unref (specified);
+}
+
+void
+gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *style,
+                                           guint                id,
+                                           GtkCssValue         *value)
+{
+  gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+  gtk_internal_return_if_fail (value != NULL);
+
+  if (style->animated_values == NULL)
+    style->animated_values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
+  if (id >= style->animated_values->len)
+   g_ptr_array_set_size (style->animated_values, id + 1);
+
+  if (g_ptr_array_index (style->animated_values, id))
+    _gtk_css_value_unref (g_ptr_array_index (style->animated_values, id));
+  g_ptr_array_index (style->animated_values, id) = _gtk_css_value_ref (value);
+
+}
+
+GtkCssValue *
+gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
+                                            guint                id)
+{
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
+
+  if (style->values == NULL ||
+      id >= style->values->len)
+    return NULL;
+
+  return g_ptr_array_index (style->values, id);
+}
+
+/* TRANSITIONS */
+
+typedef struct _TransitionInfo TransitionInfo;
+struct _TransitionInfo {
+  guint index;                  /* index into value arrays */
+  gboolean pending;             /* TRUE if we still need to handle it */
+};
+
+static void
+transition_info_add (TransitionInfo    infos[GTK_CSS_PROPERTY_N_PROPERTIES],
+                     GtkStyleProperty *property,
+                     guint             index)
+{
+  if (property == NULL)
+    {
+      guint i;
+
+      for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
+        {
+          GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
+
+          transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
+        }
+    }
+  else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
+    {
+      GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
+      guint i;
+
+      for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
+        {
+          GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
+
+          transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
+        }
+    }
+  else if (GTK_IS_CSS_STYLE_PROPERTY (property))
+    {
+      guint id;
+      
+      if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property)))
+        return;
+
+      id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property));
+      g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES);
+      infos[id].index = index;
+      infos[id].pending = TRUE;
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+}
+
+static void
+transition_infos_set (TransitionInfo  infos[GTK_CSS_PROPERTY_N_PROPERTIES],
+                      GtkCssValue    *transitions)
+{
+  guint i;
+
+  for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++)
+    {
+      GtkStyleProperty *property;
+      GtkCssValue *prop_value;
+
+      prop_value = _gtk_css_array_value_get_nth (transitions, i);
+      if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0)
+        property = NULL;
+      else
+        {
+          property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value));
+          if (property == NULL)
+            continue;
+        }
+      
+      transition_info_add (infos, property, i);
+    }
+}
+
+static GtkStyleAnimation *
+gtk_css_animated_style_find_transition (GtkCssAnimatedStyle *style,
+                                        guint                property_id)
+{
+  GSList *list;
+
+  for (list = style->animations; list; list = list->next)
+    {
+      if (!GTK_IS_CSS_TRANSITION (list->data))
+        continue;
+
+      if (_gtk_css_transition_get_property (list->data) == property_id)
+        return list->data;
+    }
+
+  return NULL;
+}
+
+static void
+gtk_css_animated_style_create_css_transitions (GtkCssAnimatedStyle *style,
+                                               gint64               timestamp,
+                                               GtkCssAnimatedStyle *source)
+{
+  TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
+  GtkCssValue *durations, *delays, *timing_functions;
+  guint i;
+
+  transition_infos_set (transitions, gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_PROPERTY));
+
+  durations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_DURATION);
+  delays = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_DELAY);
+  timing_functions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);
+
+  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
+    {
+      GtkStyleAnimation *animation;
+      GtkCssValue *start, *end;
+      double duration, delay;
+
+      if (!transitions[i].pending)
+        continue;
+
+      duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
+      delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
+      if (duration + delay == 0.0)
+        continue;
+
+      start = gtk_css_animated_style_get_intrinsic_value (source, i);
+      end = gtk_css_animated_style_get_intrinsic_value (style, i);
+      if (_gtk_css_value_equal (start, end))
+        {
+          animation = gtk_css_animated_style_find_transition (GTK_CSS_ANIMATED_STYLE (source), i);
+          if (animation)
+            style->animations = g_slist_prepend (style->animations, g_object_ref (animation));
+        }
+      else
+        {
+          animation = _gtk_css_transition_new (i,
+                                               gtk_css_style_get_value (GTK_CSS_STYLE (source), i),
+                                               _gtk_css_array_value_get_nth (timing_functions, i),
+                                               timestamp + delay * G_USEC_PER_SEC,
+                                               timestamp + (delay + duration) * G_USEC_PER_SEC);
+          style->animations = g_slist_prepend (style->animations, animation);
+        }
+    }
+}
+
+static GtkStyleAnimation *
+gtk_css_animated_style_find_animation (GtkCssAnimatedStyle *style,
+                                       const char          *name)
+{
+  GSList *list;
+
+  for (list = style->animations; list; list = list->next)
+    {
+      if (!GTK_IS_CSS_ANIMATION (list->data))
+        continue;
+
+      if (g_str_equal (_gtk_css_animation_get_name (list->data), name))
+        return list->data;
+    }
+
+  return NULL;
+}
+
+static void
+gtk_css_animated_style_create_css_animations (GtkCssAnimatedStyle     *style,
+                                              GtkCssAnimatedStyle     *parent_style,
+                                              gint64                   timestamp,
+                                              GtkStyleProviderPrivate *provider,
+                                              int                      scale,
+                                              GtkCssAnimatedStyle     *source)
+{
+  GtkCssValue *durations, *delays, *timing_functions, *animations;
+  GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
+  guint i;
+
+  animations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_NAME);
+  durations = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DURATION);
+  delays = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DELAY);
+  timing_functions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
+  iteration_counts = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
+  directions = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
+  play_states = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
+  fill_modes = gtk_css_style_get_value (GTK_CSS_STYLE (style), GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);
+
+  for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
+    {
+      GtkStyleAnimation *animation;
+      GtkCssKeyframes *keyframes;
+      const char *name;
+      
+      name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
+      if (g_ascii_strcasecmp (name, "none") == 0)
+        continue;
+
+      animation = gtk_css_animated_style_find_animation (style, name);
+      if (animation)
+        continue;
+
+      if (source)
+        animation = gtk_css_animated_style_find_animation (source, name);
+
+      if (animation)
+        {
+          animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
+                                               timestamp,
+                                               _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
+        }
+      else
+        {
+          keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
+          if (keyframes == NULL)
+            continue;
+
+          keyframes = _gtk_css_keyframes_compute (keyframes, provider, scale, GTK_CSS_STYLE (style), GTK_CSS_STYLE (parent_style));
+
+          animation = _gtk_css_animation_new (name,
+                                              keyframes,
+                                              timestamp,
+                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
+                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
+                                              _gtk_css_array_value_get_nth (timing_functions, i),
+                                              _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
+                                              _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
+                                              _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
+                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
+          _gtk_css_keyframes_unref (keyframes);
+        }
+      style->animations = g_slist_prepend (style->animations, animation);
+    }
+}
+
+/* PUBLIC API */
+
+void
+gtk_css_animated_style_create_animations (GtkCssAnimatedStyle     *style,
+                                          GtkCssAnimatedStyle     *parent_style,
+                                          gint64                   timestamp,
+                                          GtkStyleProviderPrivate *provider,
+                                          int                      scale,
+                                          GtkCssAnimatedStyle     *source)
+{
+  if (source != NULL)
+    gtk_css_animated_style_create_css_transitions (style, timestamp, source);
+  gtk_css_animated_style_create_css_animations (style, parent_style, timestamp, provider, scale, source);
+}
+
+GtkBitmask *
+gtk_css_animated_style_advance (GtkCssAnimatedStyle *style,
+                                gint64               timestamp)
+{
+  GtkBitmask *changed;
+  GPtrArray *old_computed_values;
+  GSList *list;
+  guint i;
+
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
+  gtk_internal_return_val_if_fail (timestamp >= style->current_time, NULL);
+
+  style->current_time = timestamp;
+  old_computed_values = style->animated_values;
+  style->animated_values = NULL;
+
+  list = style->animations;
+  while (list)
+    {
+      GtkStyleAnimation *animation = list->data;
+      
+      list = list->next;
+
+      _gtk_style_animation_set_values (animation,
+                                       timestamp,
+                                       GTK_CSS_ANIMATED_STYLE (style));
+      
+      if (_gtk_style_animation_is_finished (animation, timestamp))
+        {
+          style->animations = g_slist_remove (style->animations, animation);
+          g_object_unref (animation);
+        }
+    }
+
+  /* figure out changes */
+  changed = _gtk_bitmask_new ();
+
+  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
+    {
+      GtkCssValue *old_animated, *new_animated;
+
+      old_animated = old_computed_values && i < old_computed_values->len ? g_ptr_array_index (old_computed_values, i) : NULL;
+      new_animated = style->animated_values && i < style->animated_values->len ? g_ptr_array_index (style->animated_values, i) : NULL;
+
+      if (!_gtk_css_value_equal0 (old_animated, new_animated))
+        changed = _gtk_bitmask_set (changed, i, TRUE);
+    }
+
+  if (old_computed_values)
+    g_ptr_array_unref (old_computed_values);
+
+  return changed;
+}
+
+gboolean
+gtk_css_animated_style_is_static (GtkCssAnimatedStyle *style)
+{
+  GSList *list;
+
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), TRUE);
+
+  for (list = style->animations; list; list = list->next)
+    {
+      if (!_gtk_style_animation_is_static (list->data, style->current_time))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+void
+gtk_css_animated_style_cancel_animations (GtkCssAnimatedStyle *style)
+{
+  gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+
+  if (style->animated_values)
+    {
+      g_ptr_array_unref (style->animated_values);
+      style->animated_values = NULL;
+    }
+
+  g_slist_free_full (style->animations, g_object_unref);
+  style->animations = NULL;
+}
+
diff --git a/gtk/gtkcssanimatedstyleprivate.h b/gtk/gtkcssanimatedstyleprivate.h
new file mode 100644 (file)
index 0000000..07b094b
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GTK_CSS_ANIMATED_STYLE_PRIVATE_H__
+#define __GTK_CSS_ANIMATED_STYLE_PRIVATE_H__
+
+#include "gtk/gtkcssstyleprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_ANIMATED_STYLE           (gtk_css_animated_style_get_type ())
+#define GTK_CSS_ANIMATED_STYLE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyle))
+#define GTK_CSS_ANIMATED_STYLE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyleClass))
+#define GTK_IS_CSS_ANIMATED_STYLE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_ANIMATED_STYLE))
+#define GTK_IS_CSS_ANIMATED_STYLE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_ANIMATED_STYLE))
+#define GTK_CSS_ANIMATED_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_ANIMATED_STYLE, GtkCssAnimatedStyleClass))
+
+typedef struct _GtkCssAnimatedStyle           GtkCssAnimatedStyle;
+typedef struct _GtkCssAnimatedStyleClass      GtkCssAnimatedStyleClass;
+
+struct _GtkCssAnimatedStyle
+{
+  GtkCssStyle parent;
+
+  GPtrArray             *values;               /* the unanimated (aka intrinsic) values */
+  GPtrArray             *sections;             /* sections the values are defined in */
+
+  GPtrArray             *animated_values;      /* NULL or array of animated values/NULL if not animated */
+  gint64                 current_time;         /* the current time in our world */
+  GSList                *animations;           /* the running animations, least important one first */
+
+  GtkBitmask            *depends_on_parent;    /* for intrinsic values */
+  GtkBitmask            *equals_parent;        /* dito */
+  GtkBitmask            *depends_on_color;     /* dito */
+  GtkBitmask            *depends_on_font_size; /* dito */
+};
+
+struct _GtkCssAnimatedStyleClass
+{
+  GtkCssStyleClass parent_class;
+};
+
+GType                   gtk_css_animated_style_get_type         (void) G_GNUC_CONST;
+
+GtkCssStyle *           gtk_css_animated_style_new              (void);
+
+void                    gtk_css_animated_style_compute_value    (GtkCssAnimatedStyle    *style,
+                                                                 GtkStyleProviderPrivate*provider,
+                                                                int                     scale,
+                                                                 GtkCssStyle            *parent_style,
+                                                                 guint                   id,
+                                                                 GtkCssValue            *specified,
+                                                                 GtkCssSection          *section);
+void                    gtk_css_animated_style_set_animated_value(GtkCssAnimatedStyle   *style,
+                                                                 guint                   id,
+                                                                 GtkCssValue            *value);
+                                                                        
+GtkCssValue *           gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
+                                                                 guint                   id);
+
+void                    gtk_css_animated_style_create_animations(GtkCssAnimatedStyle    *style,
+                                                                 GtkCssAnimatedStyle    *parent_style,
+                                                                 gint64                  timestamp,
+                                                                 GtkStyleProviderPrivate*provider,
+                                                                int                     scale,
+                                                                 GtkCssAnimatedStyle    *source);
+GtkBitmask *            gtk_css_animated_style_advance          (GtkCssAnimatedStyle    *style,
+                                                                 gint64                  timestamp);
+void                    gtk_css_animated_style_cancel_animations(GtkCssAnimatedStyle    *style);
+gboolean                gtk_css_animated_style_is_static        (GtkCssAnimatedStyle    *style);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_ANIMATED_STYLE_PRIVATE_H__ */
index 8ffb537e83900aa690282d3fc434975aba35d2ea..601e4064cae79899eac7cd40ba3a2b874bc54ede 100644 (file)
@@ -104,7 +104,7 @@ gtk_css_animation_get_progress_from_iteration (GtkCssAnimation *animation,
 static void
 gtk_css_animation_set_values (GtkStyleAnimation    *style_animation,
                               gint64                for_time_us,
-                              GtkCssStyle *values)
+                              GtkCssAnimatedStyle  *style)
 {
   GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
   double iteration, progress;
@@ -128,8 +128,8 @@ gtk_css_animation_set_values (GtkStyleAnimation    *style_animation,
       value = _gtk_css_keyframes_get_value (animation->keyframes,
                                             i,
                                             progress,
-                                            gtk_css_style_get_intrinsic_value (values, property_id));
-      gtk_css_style_set_animated_value (values, property_id, value);
+                                            gtk_css_animated_style_get_intrinsic_value (style, property_id));
+      gtk_css_animated_style_set_animated_value (style, property_id, value);
       _gtk_css_value_unref (value);
     }
 }
index ed586016ee298ea6bef193ecb0957dd324b917d2..0e2a952a8b116a91f5667c71c648091a334a97cf 100644 (file)
@@ -106,15 +106,15 @@ void
 _gtk_css_lookup_resolve (GtkCssLookup            *lookup,
                          GtkStyleProviderPrivate *provider,
                         int                      scale,
-                         GtkCssStyle             *values,
-                         GtkCssStyle             *parent_values)
+                         GtkCssAnimatedStyle     *style,
+                         GtkCssStyle             *parent_style)
 {
   guint i, n;
 
   g_return_if_fail (lookup != NULL);
   g_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
-  g_return_if_fail (GTK_IS_CSS_STYLE (values));
-  g_return_if_fail (parent_values == NULL || GTK_IS_CSS_STYLE (parent_values));
+  g_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
+  g_return_if_fail (parent_style == NULL || GTK_IS_CSS_ANIMATED_STYLE (parent_style));
 
   n = _gtk_css_style_property_get_n_properties ();
 
@@ -122,13 +122,13 @@ _gtk_css_lookup_resolve (GtkCssLookup            *lookup,
     {
       if (lookup->values[i].value ||
           _gtk_bitmask_get (lookup->missing, i))
-        gtk_css_style_compute_value (values,
-                                     provider,
-                                     scale,
-                                     parent_values,
-                                     i,
-                                     lookup->values[i].value,
-                                     lookup->values[i].section);
+        gtk_css_animated_style_compute_value (style,
+                                              provider,
+                                              scale,
+                                              parent_style,
+                                              i,
+                                              lookup->values[i].value,
+                                              lookup->values[i].section);
       /* else not a relevant property */
     }
 }
index 897fe9e39a9dcc5ccfe557fa17ec8f423388be94..2b53e4ace66737131370d5a1c1b3a4d4cb8d3939 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <glib-object.h>
 #include "gtk/gtkbitmaskprivate.h"
-#include "gtk/gtkcssstyleprivate.h"
+#include "gtk/gtkcssanimatedstyleprivate.h"
 #include "gtk/gtkcsssection.h"
 
 
@@ -51,8 +51,8 @@ void                    _gtk_css_lookup_set                     (GtkCssLookup
 void                    _gtk_css_lookup_resolve                 (GtkCssLookup               *lookup,
                                                                  GtkStyleProviderPrivate    *provider,
                                                                 int                         scale,
-                                                                 GtkCssStyle       *values,
-                                                                 GtkCssStyle       *parent_values);
+                                                                 GtkCssAnimatedStyle        *style,
+                                                                 GtkCssStyle                *parent_style);
 
 static inline const GtkBitmask *
 _gtk_css_lookup_get_missing (const GtkCssLookup *lookup)
index 21c89a1dc5908ef5224d35dff2e2ee6330f2051c..f24557c65f2c87aa63f3fc5a3148dc019f70e9dc 100644 (file)
 #include "gtkstylepropertyprivate.h"
 #include "gtkstyleproviderprivate.h"
 
-G_DEFINE_TYPE (GtkCssStyle, gtk_css_style, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE (GtkCssStyle, gtk_css_style, G_TYPE_OBJECT)
 
-static void
-gtk_css_style_dispose (GObject *object)
+static GtkCssSection *
+gtk_css_style_real_get_section (GtkCssStyle *style,
+                                guint        id)
 {
-  GtkCssStyle *style = GTK_CSS_STYLE (object);
-
-  if (style->values)
-    {
-      g_ptr_array_unref (style->values);
-      style->values = NULL;
-    }
-  if (style->sections)
-    {
-      g_ptr_array_unref (style->sections);
-      style->sections = NULL;
-    }
-  if (style->animated_values)
-    {
-      g_ptr_array_unref (style->animated_values);
-      style->animated_values = NULL;
-    }
-
-  g_slist_free_full (style->animations, g_object_unref);
-  style->animations = NULL;
-
-  G_OBJECT_CLASS (gtk_css_style_parent_class)->dispose (object);
+  return NULL;
 }
 
-static void
-gtk_css_style_finalize (GObject *object)
+static GtkBitmask *
+gtk_css_style_real_compute_dependencies (GtkCssStyle      *style,
+                                         const GtkBitmask *parent_changes)
 {
-  GtkCssStyle *style = GTK_CSS_STYLE (object);
-
-  _gtk_bitmask_free (style->depends_on_parent);
-  _gtk_bitmask_free (style->equals_parent);
-  _gtk_bitmask_free (style->depends_on_color);
-  _gtk_bitmask_free (style->depends_on_font_size);
-
-  G_OBJECT_CLASS (gtk_css_style_parent_class)->finalize (object);
+  return _gtk_bitmask_copy (parent_changes);
 }
 
 static void
 gtk_css_style_class_init (GtkCssStyleClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->dispose = gtk_css_style_dispose;
-  object_class->finalize = gtk_css_style_finalize;
+  klass->get_section = gtk_css_style_real_get_section;
+  klass->compute_dependencies = gtk_css_style_real_compute_dependencies;
 }
 
 static void
 gtk_css_style_init (GtkCssStyle *style)
 {
-  style->depends_on_parent = _gtk_bitmask_new ();
-  style->equals_parent = _gtk_bitmask_new ();
-  style->depends_on_color = _gtk_bitmask_new ();
-  style->depends_on_font_size = _gtk_bitmask_new ();
-}
-
-GtkCssStyle *
-gtk_css_style_new (void)
-{
-  return g_object_new (GTK_TYPE_CSS_STYLE, NULL);
-}
-
-static void
-maybe_unref_section (gpointer section)
-{
-  if (section)
-    gtk_css_section_unref (section);
-}
-
-void
-gtk_css_style_compute_value (GtkCssStyle             *style,
-                             GtkStyleProviderPrivate *provider,
-                            int                      scale,
-                             GtkCssStyle             *parent_style,
-                             guint                    id,
-                             GtkCssValue             *specified,
-                             GtkCssSection           *section)
-{
-  GtkCssDependencies dependencies;
-  GtkCssValue *value;
-
-  gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
-  gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider));
-  gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
-
-  /* http://www.w3.org/TR/css3-cascade/#cascade
-   * Then, for every element, the value for each property can be found
-   * by following this pseudo-algorithm:
-   * 1) Identify all declarations that apply to the element
-   */
-  if (specified == NULL)
-    {
-      GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (id);
-
-      if (_gtk_css_style_property_is_inherit (prop))
-        specified = _gtk_css_inherit_value_new ();
-      else
-        specified = _gtk_css_initial_value_new ();
-    }
-  else
-    _gtk_css_value_ref (specified);
-
-  value = _gtk_css_value_compute (specified, id, provider, scale, style, parent_style, &dependencies);
-
-  if (style->values == NULL)
-    style->values = g_ptr_array_new_full (_gtk_css_style_property_get_n_properties (),
-                                          (GDestroyNotify)_gtk_css_value_unref);
-  if (id >= style->values->len)
-   g_ptr_array_set_size (style->values, id + 1);
-
-  if (g_ptr_array_index (style->values, id))
-    _gtk_css_value_unref (g_ptr_array_index (style->values, id));
-  g_ptr_array_index (style->values, id) = _gtk_css_value_ref (value);
-
-  if (dependencies & (GTK_CSS_DEPENDS_ON_PARENT | GTK_CSS_EQUALS_PARENT))
-    style->depends_on_parent = _gtk_bitmask_set (style->depends_on_parent, id, TRUE);
-  if (dependencies & (GTK_CSS_EQUALS_PARENT))
-    style->equals_parent = _gtk_bitmask_set (style->equals_parent, id, TRUE);
-  if (dependencies & (GTK_CSS_DEPENDS_ON_COLOR))
-    style->depends_on_color = _gtk_bitmask_set (style->depends_on_color, id, TRUE);
-  if (dependencies & (GTK_CSS_DEPENDS_ON_FONT_SIZE))
-    style->depends_on_font_size = _gtk_bitmask_set (style->depends_on_font_size, id, TRUE);
-
-  if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
-    {
-      gtk_css_section_unref (g_ptr_array_index (style->sections, id));
-      g_ptr_array_index (style->sections, id) = NULL;
-    }
-
-  if (section)
-    {
-      if (style->sections == NULL)
-        style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
-      if (style->sections->len <= id)
-        g_ptr_array_set_size (style->sections, id + 1);
-
-      g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
-    }
-
-  _gtk_css_value_unref (value);
-  _gtk_css_value_unref (specified);
-}
-
-void
-gtk_css_style_set_animated_value (GtkCssStyle *style,
-                                  guint        id,
-                                  GtkCssValue *value)
-{
-  gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
-  gtk_internal_return_if_fail (value != NULL);
-
-  if (style->animated_values == NULL)
-    style->animated_values = g_ptr_array_new_with_free_func ((GDestroyNotify)_gtk_css_value_unref);
-  if (id >= style->animated_values->len)
-   g_ptr_array_set_size (style->animated_values, id + 1);
-
-  if (g_ptr_array_index (style->animated_values, id))
-    _gtk_css_value_unref (g_ptr_array_index (style->animated_values, id));
-  g_ptr_array_index (style->animated_values, id) = _gtk_css_value_ref (value);
-
 }
 
 GtkCssValue *
@@ -209,25 +71,7 @@ gtk_css_style_get_value (GtkCssStyle *style,
 {
   gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
 
-  if (style->animated_values &&
-      id < style->animated_values->len &&
-      g_ptr_array_index (style->animated_values, id))
-    return g_ptr_array_index (style->animated_values, id);
-
-  return gtk_css_style_get_intrinsic_value (style, id);
-}
-
-GtkCssValue *
-gtk_css_style_get_intrinsic_value (GtkCssStyle *style,
-                                   guint        id)
-{
-  gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
-
-  if (style->values == NULL ||
-      id >= style->values->len)
-    return NULL;
-
-  return g_ptr_array_index (style->values, id);
+  return GTK_CSS_STYLE_GET_CLASS (style)->get_value (style, id);
 }
 
 GtkCssSection *
@@ -236,11 +80,7 @@ gtk_css_style_get_section (GtkCssStyle *style,
 {
   gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
 
-  if (style->sections == NULL ||
-      id >= style->sections->len)
-    return NULL;
-
-  return g_ptr_array_index (style->sections, id);
+  return GTK_CSS_STYLE_GET_CLASS (style)->get_section (style, id);
 }
 
 GtkBitmask *
@@ -250,369 +90,25 @@ gtk_css_style_get_difference (GtkCssStyle *style,
   GtkBitmask *result;
   guint i, len;
 
-  len = MIN (style->values->len, other->values->len);
   result = _gtk_bitmask_new ();
-  if (style->values->len != other->values->len)
-    result = _gtk_bitmask_invert_range (result, len, MAX (style->values->len, other->values->len));
-  
+  len = _gtk_css_style_property_get_n_properties ();
   for (i = 0; i < len; i++)
     {
-      if (!_gtk_css_value_equal (g_ptr_array_index (style->values, i),
-                                 g_ptr_array_index (other->values, i)))
+      if (!_gtk_css_value_equal (gtk_css_style_get_value (style, i),
+                                 gtk_css_style_get_value (other, i)))
         result = _gtk_bitmask_set (result, i, TRUE);
     }
 
   return result;
 }
 
-/* TRANSITIONS */
-
-typedef struct _TransitionInfo TransitionInfo;
-struct _TransitionInfo {
-  guint index;                  /* index into value arrays */
-  gboolean pending;             /* TRUE if we still need to handle it */
-};
-
-static void
-transition_info_add (TransitionInfo    infos[GTK_CSS_PROPERTY_N_PROPERTIES],
-                     GtkStyleProperty *property,
-                     guint             index)
-{
-  if (property == NULL)
-    {
-      guint i;
-
-      for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
-        {
-          GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
-
-          transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
-        }
-    }
-  else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
-    {
-      GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
-      guint i;
-
-      for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
-        {
-          GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
-
-          transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index);
-        }
-    }
-  else if (GTK_IS_CSS_STYLE_PROPERTY (property))
-    {
-      guint id;
-      
-      if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property)))
-        return;
-
-      id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property));
-      g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES);
-      infos[id].index = index;
-      infos[id].pending = TRUE;
-    }
-  else
-    {
-      g_assert_not_reached ();
-    }
-}
-
-static void
-transition_infos_set (TransitionInfo  infos[GTK_CSS_PROPERTY_N_PROPERTIES],
-                      GtkCssValue    *transitions)
-{
-  guint i;
-
-  for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++)
-    {
-      GtkStyleProperty *property;
-      GtkCssValue *prop_value;
-
-      prop_value = _gtk_css_array_value_get_nth (transitions, i);
-      if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0)
-        property = NULL;
-      else
-        {
-          property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value));
-          if (property == NULL)
-            continue;
-        }
-      
-      transition_info_add (infos, property, i);
-    }
-}
-
-static GtkStyleAnimation *
-gtk_css_style_find_transition (GtkCssStyle *style,
-                               guint        property_id)
-{
-  GSList *list;
-
-  for (list = style->animations; list; list = list->next)
-    {
-      if (!GTK_IS_CSS_TRANSITION (list->data))
-        continue;
-
-      if (_gtk_css_transition_get_property (list->data) == property_id)
-        return list->data;
-    }
-
-  return NULL;
-}
-
-static void
-gtk_css_style_create_css_transitions (GtkCssStyle *style,
-                                      gint64       timestamp,
-                                      GtkCssStyle *source)
-{
-  TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
-  GtkCssValue *durations, *delays, *timing_functions;
-  guint i;
-
-  transition_infos_set (transitions, gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));
-
-  durations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_DURATION);
-  delays = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_DELAY);
-  timing_functions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);
-
-  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
-    {
-      GtkStyleAnimation *animation;
-      GtkCssValue *start, *end;
-      double duration, delay;
-
-      if (!transitions[i].pending)
-        continue;
-
-      duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
-      delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
-      if (duration + delay == 0.0)
-        continue;
-
-      start = gtk_css_style_get_intrinsic_value (source, i);
-      end = gtk_css_style_get_intrinsic_value (style, i);
-      if (_gtk_css_value_equal (start, end))
-        {
-          animation = gtk_css_style_find_transition (GTK_CSS_STYLE (source), i);
-          if (animation)
-            style->animations = g_slist_prepend (style->animations, g_object_ref (animation));
-        }
-      else
-        {
-          animation = _gtk_css_transition_new (i,
-                                               gtk_css_style_get_value (source, i),
-                                               _gtk_css_array_value_get_nth (timing_functions, i),
-                                               timestamp + delay * G_USEC_PER_SEC,
-                                               timestamp + (delay + duration) * G_USEC_PER_SEC);
-          style->animations = g_slist_prepend (style->animations, animation);
-        }
-    }
-}
-
-static GtkStyleAnimation *
-gtk_css_style_find_animation (GtkCssStyle *style,
-                              const char  *name)
-{
-  GSList *list;
-
-  for (list = style->animations; list; list = list->next)
-    {
-      if (!GTK_IS_CSS_ANIMATION (list->data))
-        continue;
-
-      if (g_str_equal (_gtk_css_animation_get_name (list->data), name))
-        return list->data;
-    }
-
-  return NULL;
-}
-
-static void
-gtk_css_style_create_css_animations (GtkCssStyle             *style,
-                                     GtkCssStyle             *parent_style,
-                                     gint64                   timestamp,
-                                     GtkStyleProviderPrivate *provider,
-                                    int                      scale,
-                                     GtkCssStyle             *source)
-{
-  GtkCssValue *durations, *delays, *timing_functions, *animations;
-  GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
-  guint i;
-
-  animations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_NAME);
-  durations = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DURATION);
-  delays = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DELAY);
-  timing_functions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
-  iteration_counts = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
-  directions = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
-  play_states = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
-  fill_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);
-
-  for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
-    {
-      GtkStyleAnimation *animation;
-      GtkCssKeyframes *keyframes;
-      const char *name;
-      
-      name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
-      if (g_ascii_strcasecmp (name, "none") == 0)
-        continue;
-
-      animation = gtk_css_style_find_animation (style, name);
-      if (animation)
-        continue;
-
-      if (source)
-        animation = gtk_css_style_find_animation (source, name);
-
-      if (animation)
-        {
-          animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
-                                               timestamp,
-                                               _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
-        }
-      else
-        {
-          keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
-          if (keyframes == NULL)
-            continue;
-
-          keyframes = _gtk_css_keyframes_compute (keyframes, provider, scale, style, parent_style);
-
-          animation = _gtk_css_animation_new (name,
-                                              keyframes,
-                                              timestamp,
-                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
-                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
-                                              _gtk_css_array_value_get_nth (timing_functions, i),
-                                              _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
-                                              _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
-                                              _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
-                                              _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
-          _gtk_css_keyframes_unref (keyframes);
-        }
-      style->animations = g_slist_prepend (style->animations, animation);
-    }
-}
-
-/* PUBLIC API */
-
-void
-gtk_css_style_create_animations (GtkCssStyle             *style,
-                                 GtkCssStyle             *parent_style,
-                                 gint64                   timestamp,
-                                 GtkStyleProviderPrivate *provider,
-                                 int                      scale,
-                                 GtkCssStyle             *source)
-{
-  if (source != NULL)
-    gtk_css_style_create_css_transitions (style, timestamp, source);
-  gtk_css_style_create_css_animations (style, parent_style, timestamp, provider, scale, source);
-}
-
-GtkBitmask *
-gtk_css_style_advance (GtkCssStyle *style,
-                       gint64       timestamp)
-{
-  GtkBitmask *changed;
-  GPtrArray *old_computed_values;
-  GSList *list;
-  guint i;
-
-  gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
-  gtk_internal_return_val_if_fail (timestamp >= style->current_time, NULL);
-
-  style->current_time = timestamp;
-  old_computed_values = style->animated_values;
-  style->animated_values = NULL;
-
-  list = style->animations;
-  while (list)
-    {
-      GtkStyleAnimation *animation = list->data;
-      
-      list = list->next;
-
-      _gtk_style_animation_set_values (animation,
-                                       timestamp,
-                                       GTK_CSS_STYLE (style));
-      
-      if (_gtk_style_animation_is_finished (animation, timestamp))
-        {
-          style->animations = g_slist_remove (style->animations, animation);
-          g_object_unref (animation);
-        }
-    }
-
-  /* figure out changes */
-  changed = _gtk_bitmask_new ();
-
-  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
-    {
-      GtkCssValue *old_animated, *new_animated;
-
-      old_animated = old_computed_values && i < old_computed_values->len ? g_ptr_array_index (old_computed_values, i) : NULL;
-      new_animated = style->animated_values && i < style->animated_values->len ? g_ptr_array_index (style->animated_values, i) : NULL;
-
-      if (!_gtk_css_value_equal0 (old_animated, new_animated))
-        changed = _gtk_bitmask_set (changed, i, TRUE);
-    }
-
-  if (old_computed_values)
-    g_ptr_array_unref (old_computed_values);
-
-  return changed;
-}
-
-gboolean
-gtk_css_style_is_static (GtkCssStyle *style)
-{
-  GSList *list;
-
-  gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), TRUE);
-
-  for (list = style->animations; list; list = list->next)
-    {
-      if (!_gtk_style_animation_is_static (list->data, style->current_time))
-        return FALSE;
-    }
-
-  return TRUE;
-}
-
-void
-gtk_css_style_cancel_animations (GtkCssStyle *style)
-{
-  gtk_internal_return_if_fail (GTK_IS_CSS_STYLE (style));
-
-  if (style->animated_values)
-    {
-      g_ptr_array_unref (style->animated_values);
-      style->animated_values = NULL;
-    }
-
-  g_slist_free_full (style->animations, g_object_unref);
-  style->animations = NULL;
-}
-
 GtkBitmask *
 gtk_css_style_compute_dependencies (GtkCssStyle      *style,
                                     const GtkBitmask *parent_changes)
 {
-  GtkBitmask *changes;
-
   gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), _gtk_bitmask_new ());
 
-  changes = _gtk_bitmask_copy (parent_changes);
-  changes = _gtk_bitmask_intersect (changes, style->depends_on_parent);
-  if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
-    changes = _gtk_bitmask_union (changes, style->depends_on_color);
-  if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
-    changes = _gtk_bitmask_union (changes, style->depends_on_font_size);
-
-  return changes;
+  return GTK_CSS_STYLE_GET_CLASS (style)->compute_dependencies (style, parent_changes);
 }
 
 void
index f5664265613374876acf2830b94b7e208a07b7ed..d61b4c3cf90caf8e2ad55897c8271b5702184d3a 100644 (file)
@@ -41,62 +41,39 @@ typedef struct _GtkCssStyleClass      GtkCssStyleClass;
 struct _GtkCssStyle
 {
   GObject parent;
-
-  GPtrArray             *values;               /* the unanimated (aka intrinsic) values */
-  GPtrArray             *sections;             /* sections the values are defined in */
-
-  GPtrArray             *animated_values;      /* NULL or array of animated values/NULL if not animated */
-  gint64                 current_time;         /* the current time in our world */
-  GSList                *animations;           /* the running animations, least important one first */
-
-  GtkBitmask            *depends_on_parent;    /* for intrinsic values */
-  GtkBitmask            *equals_parent;        /* dito */
-  GtkBitmask            *depends_on_color;     /* dito */
-  GtkBitmask            *depends_on_font_size; /* dito */
 };
 
 struct _GtkCssStyleClass
 {
   GObjectClass parent_class;
+
+  /* Get the value for the given property id. This needs to be FAST. */
+  GtkCssValue *         (* get_value)                           (GtkCssStyle            *style,
+                                                                 guint                   id);
+  /* Get the section the value at the given id was declared at or NULL if unavailable.
+   * Optional: default impl will just return NULL */
+  GtkCssSection *       (* get_section)                         (GtkCssStyle            *style,
+                                                                 guint                   id);
+  /* Compute the bitmask of potentially changed properties if the parent has changed
+   * the passed in ones.
+   * This is for example needed when changes in the "color" property will affect
+   * all properties using "currentColor" as a color.
+   * Optional: The default impl just returns the parent changes unchanged */
+  GtkBitmask *          (* compute_dependencies)                (GtkCssStyle            *style,
+                                                                 const GtkBitmask       *parent_changes);
 };
 
 GType                   gtk_css_style_get_type                  (void) G_GNUC_CONST;
 
-GtkCssStyle *           gtk_css_style_new                       (void);
-
-void                    gtk_css_style_compute_value             (GtkCssStyle            *style,
-                                                                 GtkStyleProviderPrivate*provider,
-                                                                int                     scale,
-                                                                 GtkCssStyle            *parent_style,
-                                                                 guint                   id,
-                                                                 GtkCssValue            *specified,
-                                                                 GtkCssSection          *section);
-void                    gtk_css_style_set_animated_value        (GtkCssStyle            *style,
-                                                                 guint                   id,
-                                                                 GtkCssValue            *value);
-                                                                        
 GtkCssValue *           gtk_css_style_get_value                 (GtkCssStyle            *style,
                                                                  guint                   id);
 GtkCssSection *         gtk_css_style_get_section               (GtkCssStyle            *style,
                                                                  guint                   id);
-GtkCssValue *           gtk_css_style_get_intrinsic_value       (GtkCssStyle            *style,
-                                                                 guint                   id);
 GtkBitmask *            gtk_css_style_get_difference            (GtkCssStyle            *style,
                                                                  GtkCssStyle            *other);
 GtkBitmask *            gtk_css_style_compute_dependencies      (GtkCssStyle            *style,
                                                                  const GtkBitmask       *parent_changes);
 
-void                    gtk_css_style_create_animations         (GtkCssStyle            *style,
-                                                                 GtkCssStyle            *parent_style,
-                                                                 gint64                  timestamp,
-                                                                 GtkStyleProviderPrivate*provider,
-                                                                int                     scale,
-                                                                 GtkCssStyle            *source);
-GtkBitmask *            gtk_css_style_advance                   (GtkCssStyle            *style,
-                                                                 gint64                  timestamp);
-void                    gtk_css_style_cancel_animations         (GtkCssStyle            *style);
-gboolean                gtk_css_style_is_static                 (GtkCssStyle            *style);
-
 char *                  gtk_css_style_to_string                 (GtkCssStyle            *style);
 void                    gtk_css_style_print                     (GtkCssStyle            *style,
                                                                  GString                *string);
index 0d0f58119f811b0ed53ff4207db75e47ae061ef9..747bac1dc7f75f6f93acf0c6a508479c0b3a75db 100644 (file)
 G_DEFINE_TYPE (GtkCssTransition, _gtk_css_transition, GTK_TYPE_STYLE_ANIMATION)
 
 static void
-gtk_css_transition_set_values (GtkStyleAnimation *animation,
-                               gint64             for_time_us,
-                               GtkCssStyle       *style)
+gtk_css_transition_set_values (GtkStyleAnimation   *animation,
+                               gint64               for_time_us,
+                               GtkCssAnimatedStyle *style)
 {
   GtkCssTransition *transition = GTK_CSS_TRANSITION (animation);
   GtkCssValue *value, *end;
   double progress;
 
-  end = gtk_css_style_get_intrinsic_value (style, transition->property);
+  end = gtk_css_animated_style_get_intrinsic_value (style, transition->property);
 
   if (transition->start_time >= for_time_us)
     value = _gtk_css_value_ref (transition->start);
@@ -55,7 +55,7 @@ gtk_css_transition_set_values (GtkStyleAnimation *animation,
 
   if (value)
     {
-      gtk_css_style_set_animated_value (style, transition->property, value);
+      gtk_css_animated_style_set_animated_value (style, transition->property, value);
       _gtk_css_value_unref (value);
     }
 }
index 7bca5b702246d9225ec6bd58d66f33435cae016e..3c1a8876c76cfb13589602d613e56c1f918bde4f 100644 (file)
@@ -26,7 +26,7 @@ G_DEFINE_ABSTRACT_TYPE (GtkStyleAnimation, _gtk_style_animation, G_TYPE_OBJECT)
 static void
 gtk_style_animation_real_set_values (GtkStyleAnimation    *animation,
                                      gint64                for_time_us,
-                                     GtkCssStyle *values)
+                                     GtkCssAnimatedStyle  *style)
 {
 }
 
@@ -60,16 +60,16 @@ _gtk_style_animation_init (GtkStyleAnimation *animation)
 void
 _gtk_style_animation_set_values (GtkStyleAnimation    *animation,
                                  gint64                for_time_us,
-                                 GtkCssStyle *values)
+                                 GtkCssAnimatedStyle  *style)
 {
   GtkStyleAnimationClass *klass;
 
   g_return_if_fail (GTK_IS_STYLE_ANIMATION (animation));
-  g_return_if_fail (GTK_IS_CSS_STYLE (values));
+  g_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
 
   klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
 
-  return klass->set_values (animation, for_time_us, values);
+  klass->set_values (animation, for_time_us, style);
 }
 
 gboolean
index fbeb9d781701b9c127d7e1a92e5b88adb4beff6d..6981004376720337e843e5c38816224367be3195 100644 (file)
@@ -20,8 +20,7 @@
 #ifndef __GTK_STYLE_ANIMATION_PRIVATE_H__
 #define __GTK_STYLE_ANIMATION_PRIVATE_H__
 
-#include <glib-object.h>
-#include "gtkcssstyleprivate.h"
+#include "gtkcssanimatedstyleprivate.h"
 
 G_BEGIN_DECLS
 
@@ -50,14 +49,14 @@ struct _GtkStyleAnimationClass
                                                          gint64                  at_time_us);
   void          (* set_values)                          (GtkStyleAnimation      *animation,
                                                          gint64                  for_time_us,
-                                                         GtkCssStyle   *values);
+                                                         GtkCssAnimatedStyle    *style);
 };
 
 GType           _gtk_style_animation_get_type           (void) G_GNUC_CONST;
 
 void            _gtk_style_animation_set_values         (GtkStyleAnimation      *animation,
                                                          gint64                  for_time_us,
-                                                         GtkCssStyle   *values);
+                                                         GtkCssAnimatedStyle    *style);
 gboolean        _gtk_style_animation_is_finished        (GtkStyleAnimation      *animation,
                                                          gint64                  at_time_us);
 gboolean        _gtk_style_animation_is_static          (GtkStyleAnimation      *animation,
index cdd66f0cbe1054a468682aaf92b4c0160f008136..479bf14a3afa22ac3bb69fc84443aaf9ab43628e 100644 (file)
@@ -503,7 +503,7 @@ gtk_style_context_should_animate (GtkStyleContext *context)
     return FALSE;
 
   values = style_values_lookup (context);
-  if (gtk_css_style_is_static (values))
+  if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
     return FALSE;
 
   g_object_get (gtk_widget_get_settings (context->priv->widget),
@@ -704,7 +704,7 @@ build_properties (GtkStyleContext             *context,
   _gtk_css_lookup_resolve (lookup, 
                            GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
                           priv->scale,
-                           values,
+                           GTK_CSS_ANIMATED_STYLE (values),
                            priv->parent ? style_values_lookup (priv->parent) : NULL);
 
   _gtk_css_lookup_free (lookup);
@@ -734,7 +734,7 @@ style_values_lookup (GtkStyleContext *context)
       return values;
     }
 
-  values = gtk_css_style_new ();
+  values = gtk_css_animated_style_new ();
 
   style_info_set_values (info, values);
   if (gtk_style_context_is_saved (context))
@@ -772,7 +772,7 @@ style_values_lookup_for_state (GtkStyleContext *context,
 
   decl = gtk_css_node_declaration_ref (context->priv->info->decl);
   gtk_css_node_declaration_set_state (&decl, state);
-  values = gtk_css_style_new ();
+  values = gtk_css_animated_style_new ();
   build_properties (context, values, decl, NULL, NULL);
   gtk_css_node_declaration_unref (decl);
 
@@ -2696,9 +2696,9 @@ gtk_style_context_update_animations (GtkStyleContext *context,
   
   values = style_values_lookup (context);
 
-  differences = gtk_css_style_advance (values, timestamp);
+  differences = gtk_css_animated_style_advance (GTK_CSS_ANIMATED_STYLE (values), timestamp);
 
-  if (gtk_css_style_is_static (values))
+  if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
     _gtk_style_context_update_animating (context);
 
   return differences;
@@ -2805,13 +2805,15 @@ _gtk_style_context_validate (GtkStyleContext  *context,
       values = style_values_lookup (context);
 
       if (values != current)
-        gtk_css_style_create_animations (values,
-                                         priv->parent ? style_values_lookup (priv->parent) : NULL,
-                                         timestamp,
-                                         GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
-                                         priv->scale,
-                                         gtk_style_context_should_create_transitions (context) ? current : NULL);
-      if (gtk_css_style_is_static (values))
+        gtk_css_animated_style_create_animations (GTK_CSS_ANIMATED_STYLE (values),
+                                                  priv->parent ? GTK_CSS_ANIMATED_STYLE (style_values_lookup (priv->parent)) : NULL,
+                                                  timestamp,
+                                                  GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+                                                  priv->scale,
+                                                  gtk_style_context_should_create_transitions (context) 
+                                                    ? GTK_CSS_ANIMATED_STYLE (current)
+                                                    : NULL);
+      if (gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
         change &= ~GTK_CSS_CHANGE_ANIMATE;
       else
         change |= GTK_CSS_CHANGE_ANIMATE;